feat: statically extract route config exports into the route-graph IR (#93, PR-2) - #135
Conversation
…#93, PR-2) Each discovered route module's `export const config = <expression>` declaration is parsed with the TypeScript compiler (never executed) into the compiled route. The accepted grammar is documented in docs/diagnostics.md; rejected declaration shapes raise AB4805 and dynamic initializers raise AB4806 naming the offending construct and position, with the route compiling on the shared empty config. The graph digest now covers extracted configs. The parser ships as the aliased typescript-5 dependency so the workspace's typescript@7 toolchain resolution (rslib declaration generation) stays untouched.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
🦋 Changeset detectedLatest commit: b560f70 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b560f7021e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Codex review follow-ups on the static route-config extractor and script route discovery: - reject non-finite numeric literals (`1e999`, `-1e999`) with the AB4806 dynamic-config diagnostic instead of serializing Infinity as null - carry extracted object literals on a null prototype so a literal `__proto__` key stays an own property instead of invoking the legacy prototype setter - discover `.jsx` under src/scripts/ so rendered .jsx scripts reach the AB4807 gate instead of vanishing, and parse .jsx modules as JSX during config extraction
Summary
Wave 1 Lane B PR-2, building on the route-graph substrate #119 landed for #93.
export const config = <expression>declaration is statically extracted intoCompiledAgentRoute.config— a real TS/TSX parse with the TypeScript compiler; the module is never executed.docs/diagnostics.md): object literals with identifier/string/numeric property names, array literals without spreads or holes, string and substitution-free template literals, numeric literals with optional unary+/-,true/false/null, andas/satisfies/non-null/parenthesis wrappers.AB4805for rejected declaration shapes (let/var, destructuring, indirectexport { config }, function/class, missing initializer, non-object value),AB4806for a dynamic initializer naming the offending construct and position. Rejected routes compile with the shared empty config beside the error; a module without a config export compiles silently.inspect --routessurfaces them per route. Still consumer-invisible: no public authoring surface changes.typescript-5(npm:typescript@5.6.1-rc, already in the lockfile) dependency so the workspace'stypescript@7resolution — which rslib's declaration generation depends on and which has no single-file parse API — stays untouched.Verification (scoped per owner policy)
route-config-extract.test.ts(21 new tests: grammar matrix, TSX with JSX bodies, declaration-shape rejections, dynamic-construct naming and position) androute-graph.test.ts(19, including graph-level extraction, AB4806 beside the compiled route, digest coverage): green.api.test.ts+public-api.test.tsintegration (consumer declaration graph with the new module): green.pnpm typecheckcurrently fails on origin/main itself (dev-lock.test.ts(80,59)Buffer/NonSharedBuffer mismatch, landed with fix(cursor): conform local plugin artifacts to real host #131/fix(dev): include owning server URL in AB5000 #132) — pre-existing, reproduced on a pristine main worktree, unrelated to this diff.Closes nothing; tracks #93.